package pl.ps.wi.monitoring.station;

/**
* @mainpage Watchdog
<a href = "www.htm">Dokumentacja bazy danych</a> <br>
Główna pętla watchdoga - MainTask::MainTask() 

<b>Co Watchdog w ogóle robi?</b><br>
Pierwsze co robi po uruchomieniu, to ustawia sobie zmienną w tabeli up na jeden, aby następnie ściągnąć stamtąd dane: numery telefonów, rodzaje zdarzeń, wielki plik do rozpoznawania twarzy. To może chwilę potrwać. Następnie mniej więcej co sekundę zapisuje temperaturę do bazy danych. Gdy zostanie włożona karta do czytnika kart, zczytuje pin (sprytna Java nie umie czyścić bufora klawiatury, więc jeżeli wcześniej coś było wstukane, to zostanie potraktowane jako pin przy najbliższym włożeniu karty), a następnie próbuje rozpoznać twarz. Jeżeli weryfikacja zakończy się pomyślnie, rygiel otworzy się, a druga kamerka nagra krótki filmik i wyśle go na serwer. 
<p></p>

<b>Rygiel:</b><br>
Należy wykonać instrukcje opisane w \lib\libftd2xx.so.0.4.6\readme.dat
Wpis do fstab u nas był ciut inny: zamiast usbdevfs było usbfs (inaczej po mount – a pojawiały się błędy). W nowszych jądrach (np. to w ubuntu 10.04) usbfs jest w ogóle niewspierane i nie ma nawet czegoś takiego jak /proc/usb. Zalecamy skorzystanie ze starszej wersji
Rygiel ma drobny dzyndzel: jeżeli pomimo wszystkich starań cały czas jest otwarty (a watchdog nie sypie wyjątkami i wszystko gra), delikatnie przesunąć dzyndzel.


<b>Czujnik temperatury</b><br>
Łatwo się rozpada, więc ostrożnie – był przez nas dwukrotnie naprawiany. Potrzebny jest pakiet digitemp w linuxie. Jak zwraca temperaturę 85 to oznacza błąd.


<b>Czytnik kart:</b><br>
Potrzebuje pakietów: pcsc, pcsc-omnikey, pcsc-tools.


<b>Kamerki:</b><br>
Te, które dostaliśmy, wykazywały definitywny brak chęci współpracy, więc użyliśmy własnych.


<b>Telefon: </b><br>
Użyliśmy Nokii 6070 z nokiowym niebieskim kabelkiem usb. Właściwą konfigurację podpowiedział nam Wammu (graficzna nakładka na gammu). „Oczywiście” automatyczne rozpoznanie i automatyczna konfiguracja nie zadziałała. Natomiast udało się nam zobaczyć jakie są możliwości w liście rozwijanej idąc krok za krokiem z kreatorem – w ten sposób udało się nam wyczarować plik .gammurc.

*/
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;

import pl.ps.wi.monitoring.station.interfaces.DataCollector;
import pl.ps.wi.monitoring.station.services.CameraService;
import pl.ps.wi.monitoring.station.services.CardService;
import pl.ps.wi.monitoring.station.services.TemperatureService;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* @file Main.java
* @class Main
* @date 19.05.2010
* @version 1.0
*
* @brief Klasa uruchamia program ustawiając odpowiednie zmienne. Zawiera funkcję main(String [])
* 
* Zawiera (i inicjalizuje) zmienne kluczowe dla dalszego programu:
* - DBConnector conn
* - LocalConfiuration conf
* - List<DataCollector> sensors
 */
public class Main {

/**
*zmienna prywatna wykorzystywana do połączeń z bazą danych.
@ see DBConnector.java
*/
	private final DBConnector conn;

/**
*zmienna prywatna wykorzystywana do odczytywania zmiennych konfiguracyjnych
* @see LocalConfiuration.java
*/
	private final LocalConfiuration conf;

/**
* lista czujników temperatury i kamery. Przekazywana do funkcji MainTask
* @see setup()
* @see MainTask::MainTask()
*/	
	private final List<DataCollector> sensors;

	/**
	* Konstruktor
	 * Tworzy potrzebne obiekty: do pobierania konfiguracji z pliku, połaczenia z bazą danych i listę czujników.
	 */
	public Main() {
		conf = new LocalConfiuration();
		conn = new DBConnector(conf);
		sensors = new ArrayList<DataCollector>();
	}

	/**
	* Łączy się z bazą danych i ustawia wszystkie potrzebne zmienne: konfiguracyjne. Dodaje czujniki (temperatury, kamery) do listów sensorów.
	 */
	public void setup() throws SQLException {
		try {
			System.out.println("Connecting to DB...");
			conn.connect();
			System.out.println("Connection with DB established");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("Connection failed! YOU LOST!");
			e.printStackTrace();
		}

		Configuration dbConf = new Configuration(conf, conn);
		dbConf.getPhonesConfiguration();
		
		CardService cardService = new CardService();
		CardActions cardActions = new CardActions(conn);
		cardService.addCardStatusListener(cardActions);
		cardService.addLoggingAttemptListener(cardActions);

		sensors.add(new TemperatureService(conf, "ttyS0", 0));
		/* moduł został zastąpiony innym, odpowiada za to klasa Recorder
		try {
			List<Map<String, String>> cameras = conn.selectActiveCameras();
			for (Map<String, String> camMap : cameras) {
				sensors.add(new CameraService(conf, camMap.get("camId"), camMap.get("path")));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
		dbConf.start();
	}

	/**
	 * uaktywnia główny wątek. Tworzy nowy timer.
	 */
	public void start() {
		Timer mainTimer = new Timer("mainTimer", false);
		mainTimer.schedule(new MainTask(sensors, conn), 0, conf.getThreadsTimeout());
	}

	
	/**
	* wywołuje funkcje: setup i start - uruchamia program
	* @see setup(), start()
	*/
	public static void main(String[] args) {
		final Main main = new Main();
		try {
			main.setup();
		} catch (SQLException ex) {
			Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
		}
		main.start();
	}

}
